Skip to content

feat(dips): dedicated fast loop with offer-existence gate#1200

Open
MoonBoi9001 wants to merge 9 commits into
main-dipsfrom
mb9/dedicated-fast-loop-for-dips-acceptance
Open

feat(dips): dedicated fast loop with offer-existence gate#1200
MoonBoi9001 wants to merge 9 commits into
main-dipsfrom
mb9/dedicated-fast-loop-for-dips-acceptance

Conversation

@MoonBoi9001
Copy link
Copy Markdown
Member

@MoonBoi9001 MoonBoi9001 commented Apr 22, 2026

TL;DR

Some DIPs proposals were expiring before the agent got around to accepting them, and a separate failure mode was leaving allocations indexed without payment when their agreement disappeared. A dedicated 5-second acceptance loop replaces the 120-second reconcile path, an offer-existence gate prevents accepting before dipper's offer reaches the chain, and a 60-second sweep removes orphan rules so the agent stops indexing for free. No migration; the offer gate is bypassed when the indexing-payments-subgraph isn't configured.

Motivation

The indexer-agent confirms acceptance of DIPs offers on-chain via the SubgraphService contract. Today that confirmation rides the agent's 120-second reconcile cycle, so on a fresh deploy with any backlog the agent needs two cycles or more — over the 300-second deadline that recurring collection agreements give. A second failure mode shows up under load: when dipper's offer transaction is evicted from the mempool by a higher-fee neighbour, the agent walks up to a contract that has no record of the offer, the call reverts, the agent treats the revert as permanent, and the slot is lost to reassessment.

Underneath both problems sits a quieter one: when an agreement is ended out from under the agent — dipper expires it, the agent restarts mid-flow, or in-flight context is lost — the local indexing rule survives, the allocation stays open, and the indexer keeps indexing a subgraph that no longer pays. Operators see opaque revert errors and silently-running unpaid work, with no signal distinguishing "broken" from "unlucky".

Summary

  • Dedicated 5s acceptance loop replaces the 120s reconcile path.
  • Offer-existence gate prevents accepting before dipper's offer reaches the chain.
  • 60s sweep removes dips rules whose agreement has gone away.
  • Protection check narrowed to Accepted only so canceled agreements no longer strand allocations.
  • Parallel acceptance (concurrency 4), ensure hoisted to rule creation, phase logs added.
  • ABI-fragment errors classified as deterministic to avoid wasted retries.
  • Migration 24 made idempotent against pre-existing dips enum value from the deleted migration 19.
  • Bumps @graphprotocol/toolshed to 1.2.1-dips.1.

@github-project-automation github-project-automation Bot moved this to 🗃️ Inbox in Indexer Apr 22, 2026
@Maikol Maikol force-pushed the feat/dips-on-chain-cancel branch from c4d0d52 to 861cddf Compare April 22, 2026 14:29
MoonBoi9001 added a commit to edgeandnode/local-network that referenced this pull request Apr 25, 2026
The indexer-agent's DIPs accept gate (graphprotocol/indexer#1200)
queries the indexing-payments-subgraph for OfferStored entities
before calling acceptIndexingAgreement. Without a configured
endpoint the gate is a no-op and a dropped offer() tx loses the
agreement to a permanent deterministic rejection.

Set INDEXER_AGENT_INDEXING_PAYMENTS_SUBGRAPH_ENDPOINT alongside the
existing INDEXER_AGENT_OFFCHAIN_SUBGRAPHS so the agent picks up the
gate as soon as the subgraph deployment is detected.

Also add inline shellcheck directives to silence pre-existing
SC1091 / SC2153 notes the post-edit-lint hook surfaced.
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dedicated-fast-loop-for-dips-acceptance branch from 78f4c6c to 790355a Compare April 28, 2026 06:17
@MoonBoi9001 MoonBoi9001 changed the base branch from feat/dips-on-chain-cancel to feat/dips-new-subgraph April 28, 2026 06:17
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dedicated-fast-loop-for-dips-acceptance branch 3 times, most recently from 33c5e22 to 76346c1 Compare April 28, 2026 07:33
@MoonBoi9001 MoonBoi9001 changed the title feat: dedicated fast-path loop for DIPs proposal acceptance feat(dips): dedicated fast loop with offer-existence gate Apr 28, 2026
Base automatically changed from feat/dips-new-subgraph to feat/dips-on-chain-cancel April 28, 2026 19:37
Base automatically changed from feat/dips-on-chain-cancel to feat/dips-on-chain-collect April 28, 2026 20:09
@Maikol Maikol force-pushed the feat/dips-on-chain-collect branch from f792bc2 to 078630f Compare April 28, 2026 20:23
Base automatically changed from feat/dips-on-chain-collect to main-dips April 28, 2026 20:28
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dedicated-fast-loop-for-dips-acceptance branch 5 times, most recently from 2f6c404 to 4e965d5 Compare May 7, 2026 05:35
MoonBoi9001 and others added 6 commits May 13, 2026 17:52
DIPs acceptance rode the 120s reconcile cycle with no slack for the
300s RCA deadline. A 5s loop now polls and accepts, gated on the
offer existing on-chain (missing offer waits, doesn't fail). Bundles
the signedRca unpack and pre-accept rule creation the loop needs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A single slow submit stalled the serial accept loop. pMap with
concurrency 4 parallelises, while the wallet's nonce queue keeps
submits ordered. graphNode.ensure hoisted to rule creation, phase
timers added, and ABI-fragment errors marked deterministic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
If dipper expires an agreement or the agent restarts mid-flow, the
local dips rule survives but no agreement backs it, so the indexer
keeps indexing without payment. A 60s sweep removes dips rules with
no matching Accepted agreement; reconcile then closes the allocation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The reconcile-cycle callback iterated networks via mapNetworkMapped
with activeAllocations as input, but the body only calls
dipsManager.collectAgreementPayments which doesn't read it. Switch
to the simpler map() that doesn't require a per-network value.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The pre-unallocate protection check treated both Accepted and
CanceledByPayer as active, leaving allocations stranded on chain after
dipper canceled the agreement. Narrow it to Accepted only so the agent
closes the allocation as the cancel intends.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@MoonBoi9001 MoonBoi9001 force-pushed the mb9/dedicated-fast-loop-for-dips-acceptance branch from 4e965d5 to 03b692f Compare May 13, 2026 10:00
MoonBoi9001 and others added 3 commits May 13, 2026 18:04
DipsReceiptStatus was only used by the DipsCollector class which was
removed during the earlier rebase onto main-dips. ESLint's
no-unused-vars rule flagged the leftover import. Drop it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two compile errors surfaced after the rebase onto main-dips. dips.ts
uses sequentialTimerMap in the acceptance and sweep loops but the
import was dropped. sweep-allocations.test.ts constructs DipsManager
with 5 args; the constructor on main-dips takes 6.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 19-add-dips-to-decision-basis migration was deleted and folded into
migration 24-add-dips-schema. DBs that already ran 19 carry the enum
value but no 24 marker, so 24 re-runs and fails on duplicate enum.
Switch to ADD VALUE IF NOT EXISTS to keep 24 idempotent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: 🗃️ Inbox

Development

Successfully merging this pull request may close these issues.

2 participants